package com.aiwiown.snackmq.common.serialization;

import com.aiwiown.snackmq.common.exception.SerializationException;
import com.aiwiown.snackmq.common.serialization.constants.SerializerAlgorithm;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.Parser;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 基于 Google Protobuf 的二进制序列化实现。
 */
@Slf4j
public class ProtobufSerializer implements Serializer {

    private static final Map<Class<?>, Parser<?>> PARSER_CACHE = new ConcurrentHashMap<>();

    @Override
    public byte getAlgorithmId() {
        return SerializerAlgorithm.PROTOBUF;
    }

    /**
     * --- 核心修复 2: 修正方法签名以匹配接口 ---
     * 将 <T>serialize(T obj) 修改为 serialize(Object obj)
     */
    @Override
    public byte[] serialize(Object obj) {
        if (obj == null) {
            return new byte[0];
        }
        if (!(obj instanceof Message)) {
            throw new SerializationException("序列化对象必须是 com.google.protobuf.Message 的实例");
        }
        return ((Message) obj).toByteArray();
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        if (!Message.class.isAssignableFrom(clazz)) {
            throw new SerializationException("反序列化目标类必须是 com.google.protobuf.Message 的实例");
        }

        try {
            Parser<T> parser = (Parser<T>) getParser(clazz);
            return parser.parseFrom(bytes);
        } catch (InvalidProtocolBufferException e) {
            log.error("Protobuf字节反序列化为对象 {} 时失败", clazz.getName(), e);
            throw new SerializationException("Protobuf字节反序列化失败", e);
        }
    }

    /**
     * --- 核心修复 1: 实现缺失的接口方法 ---
     * Protobuf 是强类型的，不直接支持反序列化到像 List<T> 这样的泛型 Type。
     * 因此，最正确的实现是明确地抛出异常，告知调用者此操作不被支持。
     * 这样做可以防止在运行时出现意外的行为。
     */
    @Override
    public <T> T deserialize(byte[] data, Type typeOfT) {
        // 如果 Type 恰好是一个简单的 Class，我们可以委托给另一个方法。
        if (typeOfT instanceof Class) {
            @SuppressWarnings("unchecked")
            Class<T> clazz = (Class<T>) typeOfT;
            return deserialize(data, clazz);
        }

        log.error("ProtobufSerializer不支持反序列化到泛型类型: {}", typeOfT.getTypeName());
        throw new UnsupportedOperationException(
                "ProtobufSerializer does not support deserialization to generic types (like List<T> or Map<K,V>). " +
                        "Use a specific Protobuf message wrapper class instead."
        );
    }

    @SuppressWarnings("unchecked")
    private <T> Parser<T> getParser(Class<T> clazz) {
        return (Parser<T>) PARSER_CACHE.computeIfAbsent(clazz, key -> {
            try {
                Method method = key.getMethod("parser");
                return (Parser<T>) method.invoke(null);
            } catch (Exception e) {
                log.error("获取Protobuf类的Parser失败: {}", key.getName(), e);
                throw new SerializationException("无法找到或访问 " + key.getName() + " 的静态 'parser()' 方法", e);
            }
        });
    }
}